
#pragma once

#if defined(__GNUC__) || defined(__MINGW32__) || defined(__MINGW__)
    #pragma GCC diagnostic push
    #pragma GCC diagnostic ignored "-Weffc++"
#endif

namespace tools
{
    namespace variant_detail
    {
//-----------------------------------------------------------------------------------------
        template<class T, int TYPE_CATEGORY>struct TargetIterator;
//-----------------------------------------------------------------------------------------

        #define dCREATE_PRIMITIVE_ITERATORS(type_iterator)  \
            primitive::type_iterator it(var);               \
            if(beg)                                         \
                return it;                                  \
            ++it;                                           \
                return it


        template<class T>struct TargetPrimitiveIterator
        {
            typedef Step<T, primitive::Iterator, DIRECT_NORMAL, ePRIMITIVE>
                Iterator;
            typedef Step<T, primitive::ConstIterator, DIRECT_NORMAL, ePRIMITIVE>
                ConstIterator;
            typedef Step<T, primitive::ReverseIterator, DIRECT_NORMAL, ePRIMITIVE>
                ReverseIterator;
            typedef Step<T, primitive::ConstReverseIterator, DIRECT_NORMAL, ePRIMITIVE>
                ConstReverseIterator;

            static Iterator GetPrimitiveIterator(Variant& var, const bool beg)
            {
                dCREATE_PRIMITIVE_ITERATORS(Iterator);
            }
            static ReverseIterator GetPrimitiveReverseIterator(Variant& var, const bool beg)
            {
                dCREATE_PRIMITIVE_ITERATORS(ReverseIterator);
            }
            static ConstIterator GetPrimitiveConstIterator(Variant& var, const bool beg)
            {
                dCREATE_PRIMITIVE_ITERATORS(ConstIterator);
            }
            static ConstIterator GetPrimitiveConstIterator(const Variant& var, const bool beg)
            {
                dCREATE_PRIMITIVE_ITERATORS(ConstIterator);
            }
            static ConstReverseIterator GetPrimitiveConstReverseIterator(Variant& var, const bool beg)
            {
                dCREATE_PRIMITIVE_ITERATORS(ConstReverseIterator);
            }
            static ConstReverseIterator GetPrimitiveConstReverseIterator(const Variant& var, const bool beg)
            {
                dCREATE_PRIMITIVE_ITERATORS(ConstReverseIterator);
            }
        };
    //-----------------------------------------------------------------------------------------
        template<class T>struct TargetIterator<T,ePRIMITIVE>: TargetPrimitiveIterator<T>
        {
            typedef Step<T, primitive::Iterator, DIRECT_NORMAL>
                Iterator;
            typedef Step<T, primitive::ConstIterator, DIRECT_NORMAL>
                ConstIterator;
            typedef Step<T, primitive::ReverseIterator, DIRECT_NORMAL>
                ReverseIterator;
            typedef Step<T, primitive::ConstReverseIterator, DIRECT_NORMAL>
                ConstReverseIterator;

            static Iterator GetIterator(Variant& var, const bool beg)
            {
                dCREATE_PRIMITIVE_ITERATORS(Iterator);
            }
            static ReverseIterator GetReverseIterator(Variant& var, const bool beg)
            {
                dCREATE_PRIMITIVE_ITERATORS(ReverseIterator);
            }
            static ConstIterator GetConstIterator(Variant& var, const bool beg)
            {
                dCREATE_PRIMITIVE_ITERATORS(ConstIterator);
            }
            static ConstIterator GetConstIterator(const Variant& var, const bool beg)
            {
                dCREATE_PRIMITIVE_ITERATORS(ConstIterator);
            }
            static ConstReverseIterator GetConstReverseIterator(Variant& var, const bool beg)
            {
                dCREATE_PRIMITIVE_ITERATORS(ConstReverseIterator);
            }
            static ConstReverseIterator GetConstReverseIterator(const Variant& var, const bool beg)
            {
                dCREATE_PRIMITIVE_ITERATORS(ConstReverseIterator);
            }
        };


        #undef dCREATE_PRIMITIVE_ITERATORS
//-----------------------------------------------------------------------------------------
        template<class T>struct TargetIterator<T,eLINEAR>: TargetPrimitiveIterator<T>
        {
            typedef Step<T, typename T::iterator, DIRECT_NORMAL>
                Iterator;
            typedef Step<T, typename T::const_iterator, DIRECT_NORMAL>
                ConstIterator;
            typedef Step<T, typename T::reverse_iterator, DIRECT_NORMAL>
                ReverseIterator;
            typedef Step<T, typename T::const_reverse_iterator, DIRECT_NORMAL>
                ConstReverseIterator;

            static Iterator GetIterator(Variant& var, const bool beg)
            {
                auto& lenear = var.template Get<T>();
                return beg? lenear.begin(): lenear.end();
            }
            static ReverseIterator GetReverseIterator(Variant& var, const bool beg)
            {
                auto& lenear = var.template Get<T>();
                return beg? lenear.rbegin(): lenear.rend();
            }
            static ConstIterator GetConstIterator(Variant& var, const bool beg)
            {
                auto& lenear = var.template Get<T>();
                return beg? lenear.cbegin(): lenear.cend();
            }
            static ConstIterator GetConstIterator(const Variant& var, const bool beg)
            {
                auto& lenear = var.template Get<T>();
                return beg? lenear.cbegin(): lenear.cend();
            }
            static ConstReverseIterator GetConstReverseIterator(Variant& var, const bool beg)
            {
                auto& lenear = var.template Get<T>();
                return beg? lenear.crbegin(): lenear.crend();
            }
            static ConstReverseIterator GetConstReverseIterator(const Variant& var, const bool beg)
            {
                auto& lenear = var.template Get<T>();
                return beg? lenear.crbegin(): lenear.crend();
            }
        };
//-----------------------------------------------------------------------------------------
        template<class T>struct TargetIterator<T,eASSOCIATIVE>: TargetIterator<T,eLINEAR>{};
//-----------------------------------------------------------------------------------------
        template<class T>struct TargetIterator<T,eKEY_VARIANT>: TargetPrimitiveIterator<T>
        {
            static Native GetIterator(Variant& var, const bool beg)
            {
                auto& keyval = var.template Get<T>();
                auto& val = keyval.second;
                return val.GetHelper()->GetIterator(val, beg);
            }
            static Native GetReverseIterator(Variant& var, const bool beg)
            {
                auto& keyval = var.template Get<T>();
                auto& val = keyval.second;
                return val.GetHelper()->GetReverseIterator(val, beg);
            }
            static Native GetConstIterator(Variant& var, const bool beg)
            {
                auto& keyval = var.template Get<T>();
                auto& val = keyval.second;
                return val.GetHelper()->GetConstIterator(val, beg);
            }
            static Native GetConstIterator(const Variant& var, const bool beg)
            {
                auto& keyval = var.template Get<T>();
                auto& val = keyval.second;
                return val.GetHelper()->GetConstIterator(val, beg);
            }
            static Native GetConstReverseIterator(Variant& var, const bool beg)
            {
                auto& keyval = var.template Get<T>();
                auto& val = keyval.second;
                return val.GetHelper()->GetConstReverseIterator(val, beg);
            }
            static Native GetConstReverseIterator(const Variant& var, const bool beg)
            {
                auto& keyval = var.template Get<T>();
                auto& val = keyval.second;
                return val.GetHelper()->GetConstReverseIterator(val, beg);
            }
        };
//-----------------------------------------------------------------------------------------

    }//namespace value_detail
}//namespace tools


#if defined(__GNUC__) || defined(__MINGW32__) || defined(__MINGW__)
    #pragma GCC diagnostic pop
#endif
